package com.plian.system.service.pf.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.plian.Tools.*;
import com.plian.Tools.pagedata.PageData;
import com.plian.system.constant.sys.FormStatusConstant;
import com.plian.system.constant.sys.FormTypeConstant;
import com.plian.system.entity.pf.BaseDeputyDifferent;
import com.plian.system.entity.pf.DeputyDifferentDetail;
import com.plian.system.mapper.pf.BaseDeputyDifferentMapper;
import com.plian.system.model.CommonCode;
import com.plian.system.model.ListResult;
import com.plian.system.model.R;
import com.plian.system.mybatis.base.BaseFlowService;
import com.plian.system.mybatis.base.BaseServiceImpl;
import com.plian.system.mybatis.search.SearchEntity;
import com.plian.system.mybatis.search.SearchParamEntiy;
import com.plian.system.mybatis.search.TokenSearch;
import com.plian.system.mybatis.support.Condition;
import com.plian.system.mybatis.support.Query;
import com.plian.system.service.pf.IBaseDeputyDifferentService;
import com.plian.system.service.pf.IDeputyDifferentDetailService;
import com.plian.system.service.sys.code.IFormCodeService;
import com.plian.system.service.wf.FormWorkflowService;
import com.plian.system.vo.pf.BaseDeputyDifferentVO;
import com.plian.system.wrapper.pf.BaseDeputyDifferentWrapper;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestBody;

import java.util.*;
import java.util.stream.Collectors;

import static com.plian.system.constant.sys.FormStatusConstant.UNREVIEWED;
import static com.plian.system.constant.sys.FormTypeConstant.PF_DEPUTY_DIFFERENT;

/**
 * @Description: TODO
 * @Author: Take-off
 * @Date: 2023/3/10 3:51 PM
 * @Param
 * @return
 * @Version: 1.0
 **/
@Slf4j
@Service
@AllArgsConstructor
public class BaseDeputyDifferentServiceImpl extends BaseServiceImpl<BaseDeputyDifferentMapper, BaseDeputyDifferent> implements IBaseDeputyDifferentService, BaseFlowService {

    private FormWorkflowService formWorkflowService;

    private IFormCodeService formCodeService;

    private BaseDeputyDifferentWrapper baseDeputyDifferentWrapper;

    private IDeputyDifferentDetailService detailService;

    @Override
    public boolean saveOrUpdate(BaseDeputyDifferent baseDeputyDifferent) {
        if (!Optional.ofNullable(baseDeputyDifferent.getStatus()).isPresent()) {
            baseDeputyDifferent.setStatus(FormStatusConstant.UNREVIEWED);
        }
        if (baseDeputyDifferent.getStatus().equals(FormStatusConstant.REJECT)) {
            baseDeputyDifferent.setStatus(FormStatusConstant.UNREVIEWED);
        }
        if (!Optional.ofNullable(baseDeputyDifferent.getId()).isPresent()) {
            baseDeputyDifferent.setCode(formCodeService.getCode(FormTypeConstant.PF_DEPUTY_DIFFERENT));
            baseDeputyDifferent.setFormType(String.valueOf(FormTypeConstant.PF_DEPUTY_DIFFERENT));
        }

        return super.saveOrUpdate(baseDeputyDifferent);
    }

    @Override
    @Transactional(rollbackFor=RuntimeException.class)
    public boolean deleteLogic(List<Long> ids) {
        for (Long id : ids) {
            BaseDeputyDifferent baseDeputyDifferent = getById(id);
            if (baseDeputyDifferent == null) {
                return false;
            } else if (baseDeputyDifferent.getStatus() != null &&
                    (baseDeputyDifferent.getStatus() != FormStatusConstant.STASH && baseDeputyDifferent.getStatus() != FormStatusConstant.UNREVIEWED)) {
                return false;
            }
            formWorkflowService.deleteProcessInstance(String.valueOf(id));
        }

        boolean result = super.deleteLogic(ids);
        if (result){
            detailService.deleteByParentId(ids);
        }
        return result;
    }

    @Override
    public HashMap<String,Object> commit(String id) {
        handleStatus(Long.valueOf(id), FormStatusConstant.FLOW);
        //将需要提交的流程变量返回，用于工作流侧
        return new HashMap<String,Object>();
    }

    @Override
    public Boolean finish(String id) {
        return handleStatus(Long.valueOf(id), FormStatusConstant.FINISH);
    }

    @Override
    public Boolean reject(String id, int formState, String comment) {
        return handleStatus(Long.valueOf(id), formState);
    }

    @Override
    public List<PageData> findByIds(List<String> formIds) {
        LambdaQueryWrapper<BaseDeputyDifferent> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(BaseDeputyDifferent::getId, Func.toLongList(StringUtils.join(formIds, StringPool.COMMA)));
        List<BaseDeputyDifferent> baseDeputyDifferents = list(queryWrapper);
        List<BaseDeputyDifferentVO> baseDeputyDifferentVOS = baseDeputyDifferentWrapper.entityToVO(baseDeputyDifferents);
        List<PageData> pageDataList = new ArrayList<>();
        try{
            if (CollectionUtil.isNotEmpty(baseDeputyDifferentVOS)){
                for (BaseDeputyDifferentVO vo : baseDeputyDifferentVOS){
                    PageData pd = new PageData();
                    pd.put("id", vo.getId());
                    pd.put("UNITNAME", vo.getFillingUnitName());
                    pd.put("APPLICANTNAME", vo.getCreateUserName());
                    pd.put("applicantId", vo.getCreateUser());
                    pd.put("applyOrganizationId", vo.getFillingUnitId());
                    pd.put("formType", vo.getFormType());
                    pd.put("orgName", vo.getFillingUnitName());
                    pageDataList.add(pd);
                }
            }

            return pageDataList;
        } catch (Exception e) {
            log.error(ExceptionUtils.getFullStackTrace(e));
        }
        return pageDataList;
    }

    @Override
    public List<Integer> getFormType() {
        return Arrays.asList(PF_DEPUTY_DIFFERENT);
    }

    @Override
    public void goBackToStash(String formId) {
        handleStatus(Long.valueOf(formId), UNREVIEWED);
    }

    @Override
    @Transactional(rollbackFor=RuntimeException.class)
    public boolean submit(BaseDeputyDifferent baseDeputyDifferent) {
        //删除之前的明细
        if (baseDeputyDifferent.getId() != null){
            List<Long> ids = Collections.singletonList(baseDeputyDifferent.getId());
            detailService.deleteByParentId(ids);
        }
        boolean result = saveOrUpdate(baseDeputyDifferent);
        if (result){
            List<DeputyDifferentDetail> details = baseDeputyDifferent.getDeputyDifferentDetails();
            if (CollectionUtil.isNotEmpty(details)){
                for (DeputyDifferentDetail detail : details){
                    detail.setBaseId(baseDeputyDifferent.getId());
                    detail.setYear(baseDeputyDifferent.getDeclareYear());
                    detailService.saveOrUpdate(detail);
                }
            }
        }
        return result;
    }


    /**
     * 统一处理状态机事件方法
     *
     * @param id          主键
     * @param updateStatus  更新状态
     * @return boolean
     */
    private Boolean handleStatus(Long id, int updateStatus) {
        try {
            BaseDeputyDifferent baseDeputyDifferent = getById(id);
            /**
             * 设置审批人和审批时间
             */
            if (updateStatus == FormStatusConstant.FINISH){
                baseDeputyDifferent.setApprovedUser(TokenUtil.getTokenUserId());
                Date now = DateUtil.now();
                baseDeputyDifferent.setApprovedTime(now);
            }
            baseDeputyDifferent.setStatus(updateStatus);
            updateById(baseDeputyDifferent);
            return true;
        } catch (Exception e) {
            log.error(ExceptionUtils.getFullStackTrace(e));
            return false;
        }
    }

    @Override
    public R<BaseDeputyDifferentVO> getDetailObj(BaseDeputyDifferent baseDeputyDifferent) {
        BaseDeputyDifferent detail = getOne(Condition.getQueryWrapper(baseDeputyDifferent));
        BaseDeputyDifferentVO baseDeputyDifferentVO = baseDeputyDifferentWrapper.entityToVO(detail);
        if (Optional.ofNullable(baseDeputyDifferentVO).isPresent()){
            List<Map<String,Object>> details = getMapDetails(baseDeputyDifferentVO.getOfficeYearStart(),baseDeputyDifferentVO.getOfficeYearEnd());
            baseDeputyDifferentVO.setDetails(details);
        }
        return R.data(baseDeputyDifferentVO);
    }

    /**
     * @Description: //TODO 根据时间区间获取详情
     * @Author: Take-off
     * @Date: 4:52 PM 2023/3/10
     * @Param: [officeYearStart, officeYearEnd]
     * @return: java.util.List<java.util.Map<java.lang.String,java.lang.Object>>
     **/
    @Override
    public List<Map<String,Object>> getMapDetails(String officeYearStart,String officeYearEnd){
        List<Map<String,Object>> details = new ArrayList<>();
        List<BaseDeputyDifferent> baseDeputyDifferents = list(new LambdaQueryWrapper<BaseDeputyDifferent>().eq(BaseDeputyDifferent::getOfficeYearStart, officeYearStart)
                .eq(BaseDeputyDifferent::getOfficeYearEnd, officeYearEnd));
        if (CollectionUtil.isNotEmpty(baseDeputyDifferents)){
            List<DeputyDifferentDetail> deputyDifferentDetails = detailService.list(new LambdaQueryWrapper<DeputyDifferentDetail>().in(DeputyDifferentDetail::getBaseId,
                    baseDeputyDifferents.stream().map(BaseDeputyDifferent::getId).collect(Collectors.toList())));
            if (CollectionUtil.isNotEmpty(deputyDifferentDetails)){
                Map<String, List<DeputyDifferentDetail>> detailByIndex = deputyDifferentDetails.stream().filter(m -> Optional.ofNullable(m.getStaffId()).isPresent()).collect(Collectors.groupingBy(DeputyDifferentDetail::getIndexNum));
                Set<String> indexNums = detailByIndex.keySet();
                for (String index :indexNums){
                    Map<String, Object> map = new HashMap<>(11);
                    map.put("indexNum",index);
                    List<DeputyDifferentDetail> differentDetails = detailByIndex.get(index);
                    //年度
                    Map<String, List<DeputyDifferentDetail>> groupByYear = differentDetails.stream().filter(m -> Optional.ofNullable(m.getYear()).isPresent()).collect(Collectors.groupingBy(DeputyDifferentDetail::getYear));
                    Set<String> years = groupByYear.keySet();
                    for (String year:years){
                        map.put("year",year);
                        DeputyDifferentDetail differentDetail = groupByYear.get(year).get(0);
                        map.put("baseId",differentDetail.getBaseId().toString());
                        map.put("staffId",differentDetail.getStaffId().toString());
                        map.put("staffName",differentDetail.getStaffName());
                        map.put(year+"_score",differentDetail.getScore());
                        map.put(year+"_coefficient",differentDetail.getCoefficient());
                    }
                    //合计
                    Optional<DeputyDifferentDetail> sumDetails = differentDetails.stream().filter(m -> Optional.ofNullable(m.getIsSum()).isPresent() && m.getIsSum() == 1).findFirst();
                    if (sumDetails.isPresent()){
                        DeputyDifferentDetail sumDetail = sumDetails.get();
                        map.put("sum_score",sumDetail.getScore());
                        map.put("sum_coefficient",sumDetail.getCoefficient());
                    }
                    details.add(map);
                }
            }
        }
        return details;
    }

    @Override
    public ListResult<BaseDeputyDifferentVO> list(@RequestBody Query query) {
        List<SearchEntity> entityList = query.getSearch();
        if (query.getAscs()==null&&query.getDescs()==null){
            query.setDescs("create_time");
        }
        QueryWrapper<BaseDeputyDifferent> queryWrapper = SearchParamEntiy.getQueryWrapper(
                Condition.getQueryWrapper(new BaseDeputyDifferent()), entityList
        );

        TokenSearch<BaseDeputyDifferent> tokenSearch = new TokenSearch<>();
		tokenSearch.addTokenQuery(queryWrapper, query);

        IPage<BaseDeputyDifferent> pages = page(Condition.getPage(query), queryWrapper);
        List<BaseDeputyDifferentVO> baseDeputyDifferentVOS = baseDeputyDifferentWrapper.entityToVO(pages.getRecords());
        if (CollectionUtil.isNotEmpty(baseDeputyDifferentVOS)){
            setIsNest(baseDeputyDifferentVOS);
        }
        ListResult<BaseDeputyDifferentVO> listResult = new ListResult<>(CommonCode.SUCCESS);
        listResult.setList(baseDeputyDifferentVOS);
        listResult.setTotal(Long.valueOf(pages.getTotal()).intValue());
        return listResult;
    }

    /**
     * @Description: //TODO 判断是否需要申报下一年度
     * @Author: Take-off
     * @Date: 10:29 AM 2023/3/14
     * @Param: [baseDeputyDifferentVOS]
     * @return: void
     **/
    private void setIsNest(List<BaseDeputyDifferentVO> baseDeputyDifferentVOS){
        //获取全部
        List<BaseDeputyDifferent> allDifferents = list();
        for (BaseDeputyDifferentVO vo:baseDeputyDifferentVOS){
            if (vo.getDeclareYear().equals(vo.getOfficeYearEnd())){
                vo.setIsHaveNest(1);
            }else {
                String nextYear = DateUtil.format(DateUtil.plusYears(DateUtil.parse(vo.getDeclareYear(), DateUtil.PATTERN_YEAR), 1), DateUtil.PATTERN_YEAR);
                List<BaseDeputyDifferent> nextDifferents = allDifferents.stream().filter(m -> vo.getFillingUnitId().equals(m.getFillingUnitId()) && nextYear.equals(m.getDeclareYear())).collect(Collectors.toList());
                if (CollectionUtil.isNotEmpty(nextDifferents)){
                    vo.setIsHaveNest(1);
                }else {
                    vo.setIsHaveNest(0);
                }

            }
        }

    }





}




